package org.uds.android.fitdroid.demo.activity.spatial;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.StringTokenizer;

import org.uds.android.fitdroid.demo.apis.EventDataSQLHelper;
import org.uds.android.fitdroid.demo.apis.R;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class Demo extends Activity implements LocationListener {

	private String latitude;
	private String longitude;
	private String altitude;
	private EventDataSQLHelper eventsData;
	private EditText resdistance;
	private EditText avgspeed;
	private EditText speedtest;
	private TextView output;
	// private TextView gpsdata;
	private Button delete;
	private Button distance;
	private LocationManager locMgrGPS = null;
	private double currentdistance = 0;
	private Location oldlocation = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		output = (TextView) findViewById(R.id.output);
		output.setMovementMethod(new ScrollingMovementMethod());
		output.computeScroll();

		resdistance = (EditText) findViewById(R.id.calcDistance);

		avgspeed = (EditText) findViewById(R.id.Speed);

		speedtest = (EditText) findViewById(R.id.Speedtest);

		/*
		 * gpsdata = (TextView) findViewById(R.id.gpsdata); gpsdata.setText("");
		 * gpsdata.setMovementMethod(new ScrollingMovementMethod());
		 * gpsdata.computeScroll();
		 */

		delete = (Button) findViewById(R.id.Delete);
		delete.setOnClickListener(mdeleteListener);

		distance = (Button) findViewById(R.id.Distance);
		distance.setOnClickListener(mdistanceListener);

		locMgrGPS = (LocationManager) this
				.getSystemService(Context.LOCATION_SERVICE);
		// attr 2 = every x ms look for an update
		// attr 3 = every x meters position changing update
		locMgrGPS.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1,
				this);

		eventsData = new EventDataSQLHelper(this);
		// addEvent("First GPS Location");
		Cursor cursor = getEvents();
		showEvents(cursor);
	}

	@Override
	public void onDestroy() {
		eventsData.close();
		super.onDestroy();
	}

	private void addEvent(String title) {
		SQLiteDatabase db = eventsData.getWritableDatabase();

		// Gpsdata Table
		ContentValues values = new ContentValues();
		values.put(EventDataSQLHelper.LATITUDE, this.latitude);
		values.put(EventDataSQLHelper.LONGITUDE, this.longitude);
		values.put(EventDataSQLHelper.ALTITUDE, this.altitude);
		values.put(EventDataSQLHelper.DATE, now("yyyy.MM.dd"));
		values.put(EventDataSQLHelper.TIME, now("H:mm:ss"));
		Long gpsid = db.insert(EventDataSQLHelper.GPSDATA, null, values);

		// Tconstist table
		db = eventsData.getWritableDatabase();
		values = new ContentValues();
		values.put("trackid", 1);
		values.put("gpsdataid", gpsid);
		db.insert(EventDataSQLHelper.TCONSITS, null, values);

	}

	private Cursor getEvents() {
		SQLiteDatabase db = eventsData.getReadableDatabase();
		Cursor cursor = db.query(EventDataSQLHelper.GPSDATA, null, null, null,
				null, null, null);

		startManagingCursor(cursor);
		return cursor;
	}

	private void showEvents(Cursor cursor) {
		StringBuilder ret = new StringBuilder("");
		while (cursor.moveToNext()) {
			long id = cursor.getLong(0);
			String latitude2 = cursor.getString(1);
			String longitude2 = cursor.getString(2);
			String altitude2 = cursor.getString(3);
			ret.append(id + "\n \t latitude " + latitude2 + "\n \t longitude :"
					+ longitude2 + "\n \t altitude :" + altitude2 + "\n");
		}
		output.setText(ret);
	}

	@Override
	public void onLocationChanged(Location location) {
		// TODO Auto-generated method stub
		this.latitude = String.valueOf(location.getLatitude());
		this.longitude = String.valueOf(location.getLongitude());
		this.altitude = String.valueOf(location.getAltitude());
		addEvent("Update");
		speedtest.setText((location.getSpeed() * (3.6)) + "km/h");
		if (oldlocation == null) {
			oldlocation = location;
			avgspeed.setText("0 km");
			currentdistance = 0;
		} else {
			currentdistance += (oldlocation.distanceTo(location) / 1000);
			oldlocation = location;
			avgspeed.setText(currentdistance + "km");
		}

		// this.gpsdata.append("\n\tLatitude: "+location.getLatitude()
		// +"\n\tLongitude: " + location.getLongitude()+"\n\tAltitude: " +
		// location.getAltitude()+"\n");
		/*
		 * Cursor cursor = getEvents(); showEvents(cursor);
		 */
	}

	private OnClickListener mdeleteListener = new OnClickListener() {
		public void onClick(View v) {
			// do something when the button is clicked
			SQLiteDatabase db = eventsData.getWritableDatabase();
			db.delete(EventDataSQLHelper.GPSDATA, null, null);

			output.setText("");
			Cursor cursor = getEvents();
			showEvents(cursor);
		}
	};

	private OnClickListener mdistanceListener = new OnClickListener() {
		public void onClick(View v) {
			// do something when the button is clicked
			double[] res = calctrackdistance(1);
			resdistance.setText(String.valueOf(res[0]) + " km");

			// avgspeed.setText(String.valueOf(res[1])+" km/h");
		}
	};

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub

	}

	// returns total distance of a track
	public double[] calctrackdistance(int Trackid) {

		LinkedList<Integer> Gpsidset = new LinkedList<Integer>();
		Cursor cursor;
		double totaldistance = 0;
		int counter = 0;

		String startlong = "";
		String startlati = "";
		String endlong = "";
		String endlati = "";

		// get all the gpsids
		SQLiteDatabase db = eventsData.getReadableDatabase();

		cursor = db.query(EventDataSQLHelper.TCONSITS,
				new String[] { "gpsdataid" }, "trackid=" + Trackid, null, null,
				null, "_id");
		startManagingCursor(cursor);
		while (cursor.moveToNext()) {
			Gpsidset.add(cursor.getInt(0));
		}

		// check if there is still a point left to measure the distance
		while (counter + 1 < Gpsidset.size()) {
			// get 2 points to calc the distance
			cursor = db.query(EventDataSQLHelper.GPSDATA, new String[] {
					"latitude", "longitude" }, "_id=" + Gpsidset.get(counter),
					null, null, null, null);
			startManagingCursor(cursor);

			while (cursor.moveToNext()) {
				startlati = cursor.getString(0);
				startlong = cursor.getString(1);
			}

			cursor = db.query(EventDataSQLHelper.GPSDATA, new String[] {
					"latitude", "longitude" },
					"_id=" + Gpsidset.get(counter + 1), null, null, null, null);
			startManagingCursor(cursor);

			while (cursor.moveToNext()) {
				endlati = cursor.getString(0);
				endlong = cursor.getString(1);
			}
			// add the distance to the totaldistance
			totaldistance += calcdistance(startlong, startlati, endlong,
					endlati);

			counter++;
		}

		// calc Start+ End Time
		int timediff = 0;
		if (Gpsidset.size() > 1) {
			String starttime = "";
			String endtime = "";
			cursor = db.query(EventDataSQLHelper.GPSDATA, new String[] {
					"time", "date" }, "_id=" + Gpsidset.get(0), null, null,
					null, null);
			startManagingCursor(cursor);

			while (cursor.moveToNext()) {
				starttime = cursor.getString(0);
			}

			cursor = db.query(EventDataSQLHelper.GPSDATA, new String[] {
					"time", "date" },
					"_id=" + Gpsidset.get(Gpsidset.size() - 1), null, null,
					null, null);
			startManagingCursor(cursor);

			while (cursor.moveToNext()) {
				endtime = cursor.getString(0);
			}

			timediff = converttime(endtime) - converttime(starttime);
			timediff *= (60 * 60);
		}

		double[] res = new double[] { totaldistance, (totaldistance / timediff) };
		return res;

	}

	// returns distance in km between 2 points
	public double calcdistance(String startlong, String startlati,
			String endlong, String endlati) {
		double lon1 = Float.valueOf(startlong);
		double lon2 = Float.valueOf(endlong);

		double lat1 = Float.valueOf(startlati);
		double lat2 = Float.valueOf(endlati);

		double R = 6371; // km
		double dLat = Math.toRadians(lat2 - lat1);
		double dLon = Math.toRadians(lon2 - lon1);
		double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
				+ Math.cos(Math.toRadians(lat1))
				* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
				* Math.sin(dLon / 2);
		double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		double d = R * c;

		return d;
	}

	private String now(String dateFormat) {
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		return sdf.format(cal.getTime());

	}

	private int converttime(String time) {
		StringTokenizer tokenizer = new StringTokenizer(time, ":");
		int counter = 0;

		int res = 0;
		while (tokenizer.hasMoreTokens()) {
			if (counter == 0) {
				res += Integer.valueOf(tokenizer.nextToken()) * 60 * 60;
			} else if (counter == 1) {
				res += Integer.valueOf(tokenizer.nextToken()) * 60;
			} else {
				res += Integer.valueOf(tokenizer.nextToken());
			}
		}
		return res;
	}
}